package com.rupertjones.globalcron.web;

import com.rupertjones.globalcron.domain.Role;
import com.rupertjones.globalcron.domain.Setting;
import com.rupertjones.globalcron.domain.SettingType;
import com.rupertjones.globalcron.domain.User;
import net.sourceforge.stripes.action.Before;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;

import java.util.Collection;

/**
 * <p>&copy Rupert Jones 2011,2012</p>
 *
 * @author rup
 */
public class AddUserAction extends AbstractFormAction {

    @ValidateNestedProperties({
            @Validate(field = "password", required = true, on = { "SaveOrUpdate" }),
            @Validate(field = "fullName", required = true, on = { "SaveOrUpdate" }),
            @Validate(field = "username", required = true, on = { "SaveOrUpdate" })
    })
    private FormUser formUser;

    private Setting passwordPolicy;

    @Before(stages = LifecycleStage.BindingAndValidation)
    public void loadAndBind() {
        passwordPolicy = getSettingsService().find(SettingType.PASSWORD_POLICY);
        formUser = new FormUser(passwordPolicy);

        formUser.clearRoles();

        for(Role role : getRoles()) {
            FormRole formRole = new FormRole();
            formRole.setName(role.getName());
            formRole.setAssigned(false);
            formUser.addRole(formRole);
        }
    }

    @DefaultHandler
    public Resolution view() {
        return new ForwardResolution("/WEB-INF/jsp/add_user.jsp");
    }

    @HandlesEvent("SaveOrUpdate")
    public Resolution onSave() {

        for(int index = 0; index < getRoles().size(); index++) {
            String value = getContext().getRequest().getParameter(String.format("%s_%s", "roles", String.valueOf(index)));
            if (value != null) {
                formUser.getRole(value).setAssigned(true);
            }
        }

        boolean passwordMatch = this.formUser.isPasswordMatch();
        boolean compliant = this.formUser.isPasswordPolicyCompliant();
        ValidationErrors errors = new ValidationErrors();


        if(!passwordMatch) {
            errors.add("password", new LocalizableError("password.nomatch"));
        }

        if(!compliant) {
            errors.add("password", new SimpleError(passwordPolicy.getDescription()));
        }

        User otherUser = getUserService().findUser(this.formUser.getUsername());
        if(otherUser != null) {
            errors.add("username", new SimpleError("That username is not available"));
        }

        if(formUser.getRoles().isEmpty()) {
            errors.add("roles", new SimpleError("You must select one role"));
        }

        if (errors.size() == 0) {
            User user = new User();
            user.setFullName(this.formUser.getFullName());
            user.setUsername(this.formUser.getUsername());

            user.clearRoles();
            for(FormRole thisRole : formUser.getRoles())  {
                if(thisRole.isAssigned()) {
                    user.addRole(getUserService().findRole(thisRole.getName()));
                }
            }

            getUserService().saveWithPassword(user, this.formUser.getPassword());
            return new ForwardResolution("InfoUsers.action");
        } else {
            getContext().setValidationErrors(errors);
            return getContext().getSourcePageResolution();
        }
    }

    public FormUser getUser() {
        return formUser;
    }

    private Collection<Role> getRoles() {
        return getUserService().findAllRoles();
    }
}
